<template>
  <div class="webOUI">
    <el-row :gutter="12">
      <el-col :span="6">
        <el-card shadow="never">
          <el-input
            v-model="filterText"
            :placeholder="`${$t('Enter_keywords_to_filter')}`"/>
          <el-tree
            ref="tree"
            :data="treeData"
            :props="defaultProps"
            :filter-node-method="filterNode"
            :default-expanded-keys="defaultExpandedKeys"
            accordion
            highlight-current
            node-key="id"
            @node-click="handleNodeClick"
          >
            <span slot-scope="{ node,data }">
              <span :style="{display: 'inlie-block', width: '100%', cursor: data.disabled ?'not-allowed' : ''}">
                <span :style="{paddingRight: '14px', fontSize: '14px'}">{{ node.label }} {{ data.status ? [ data.status ]: '' }}</span>
                <el-button v-show="node.level === 4" :disabled="data.disabled" type="text" @click="queryInfo(data, node)">Query</el-button>
              </span>
            </span>
          </el-tree>
        </el-card>
      </el-col>
      <el-col :span="18">
        <el-card :style="{ marginBottom: '10px' }" shadow="never">
          <el-row :gutter="20">
            <el-col :span="12" :style="{fontSize: '14px'}">{{ $t('eqpName') }}: {{ eqpId }}</el-col>
            <el-col :span="12" :style="{fontSize: '14px'}">{{ $t('eqpstatus') }}: {{ eqpstatus }}</el-col>
          </el-row>
        </el-card>
        <el-card shadow="never">
          <div :style="{ marginBottom: '20px' }">
            <el-button :disabled="isTrackOut" type="primary" @click="handleCancel">Cancel</el-button>
            <el-button :loading="trackInLaoding" :disabled="!isTrackOut" type="primary" @click="handleTrackIn">TrackIn</el-button>
            <el-button
              :disabled="isTrackOut"
              type="primary"
              @click="handleTrackOut">TrackOut</el-button>
              <!-- <el-button type="primary" @click="handleJobAbort">{{
              $t("jobAbort")
            }}</el-button> -->
              <!-- <el-button type="primary">RT</el-button> -->
          </div>
          <el-form :inline="true" :model="infoForm" label-width="120px">
            <el-form-item :label="$t('LotNumebr')">
              <el-input v-model="infoForm.lotId" :readonly="!isTrackOut" @keyup.enter.native="getlotInfo">
                <el-button slot="append" :disabled="!isTrackOut" @click="getlotInfo">Get</el-button>
              </el-input>
            </el-form-item>
            <el-form-item :label="$t('workOrder')">
              <el-input v-model="infoForm.workOrder" readonly/>
            </el-form-item>
            <el-form-item :label="$t('productType')">
              <el-input v-model="infoForm.productType" readonly/>
            </el-form-item>
            <el-form-item :label="$t('rawMaterialCode')">
              <el-input v-model="infoForm.materialCode" readonly/>
            </el-form-item>
            <el-form-item :label="$t('processFlowNumber')">
              <el-input v-model="infoForm.processId" readonly/>
            </el-form-item>
            <el-form-item :label="$t('pathDescription')">
              <el-input v-model="infoForm.routeDesc" readonly/>
            </el-form-item>
            <el-form-item label="Recipe ID">
              <el-input v-model="infoForm.recipeName" readonly/>
            </el-form-item>
            <el-form-item :label="$t('stepId')">
              <el-input v-model="infoForm.stepDesc" readonly/>
            </el-form-item>
            <el-form-item :label="$t('completedJobsNums')">
              <el-input v-model="infoForm.lotQty" readonly/>
            </el-form-item>
            <el-form-item :label="$t('productName')">
              <el-input v-model="infoForm.product" readonly/>
            </el-form-item>
          </el-form>
        </el-card>
        <div v-show="isShow" class="swiper-message">
          <div style="font-size: 16px;padding: 8px;">Tooling</div>
          <el-form :inline="true" :model="infoForm" label-width="120px">
            <div>
              <el-form-item v-for="item of toolingTypeList" :label="item.typeName" :key="item.id">
                <el-input v-model="item.barcode" />
              </el-form-item>
            </div>
            <div>
              <el-form-item v-for="item of materialTypeList" :label="item.typeName" :key="item.id">
                <el-input v-model="item.barcode" />
              </el-form-item>
            </div>
          </el-form>
        </div>
        <div class="swiper-message">
          <div :style="messageStyles" class="swiper-content">
            <div v-for="(item, index) in msgList" :key="index" class="swiper-message-item">
              <span>[{{ item.date }}]</span>
              <span :style="{color: item.color}" class="item-message">{{ item.message }}</span>
            </div>
          </div>
        </div>
      </el-col>
    </el-row>
    <modelCancel ref="modelCancel" @initList="initList" />
    <modelTrackOut ref="modelTrackOut" @trackOutGetLotInfo="trackOutGetLotInfo"/>
    <modelJobAbort ref="modelJobAbort" />
  </div>
</template>

<script>
// import { getEqpListTree } from '@/api/maintenance/planManage'
import { getTreeList } from '@/api/equipment/prodTreeNode'
import { getLotInfo,
  doTrackIn,
  getLotInfoByEqpId,
  updateEqpStatus,
  getEqpStatusByEAP,
  checkToolingMaterialInfo,
  getToolingMaterialInfo
} from '@/api/production/webOUI'
import modelTrackOut from './components/modelTrackOut.vue'
import modelJobAbort from './components/modelJobAbort.vue'
import modelCancel from './components/modelCancel.vue'
import { deepCopy } from '@/utils/myTools'
import { Socket } from '@/utils/websocket'
import { replaceStr } from '@/utils/notification'
const typeColor = {
  Info: '#303133',
  Alarm: '#C03639',
  Success: '#30B08F',
  Primary: '#409EFF'
}

export default {
  name: 'WebOUI',
  components: { modelTrackOut, modelJobAbort, modelCancel },
  data() {
    return {
      filterText: '',
      treeData: [],
      defaultExpandedKeys: [],
      defaultProps: { label: 'name', children: 'childList' },
      eqpId: '',
      eqpName: '',
      eqpstatus: '',
      trackInLaoding: false,
      isTrackOut: true,
      infoForm: {
        lotId: ''
      },
      msgList: [],
      toolingList: [],
      toolingTypeList: [],
      materialTypeList: [],
      isShow: 0,
      interval: null,
      messageStyles: {
        transform: 'translate(0, 0px)',
        transition: 'all 0s ease-out'
      },
      disabledList: [],
      socket: null,
      arr: []
    }
  },
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val)
    }
  },
  created() {
    this.getEqpTree()
  },
  destroyed() {
    this.interval = null
    this.socket.close()
  },
  methods: {
    initList() {
      this.eqpId = ''
      this.eqpName = ''
      this.eqpstatus = ''
      this.trackInLaoding = false
      this.isTrackOut = true
      this.infoForm = {}
      this.$refs.tree.setCheckedKeys([])
    },
    trackOutGetLotInfo(lotId) {
      this.eqpId = ''
      this.eqpName = ''
      this.eqpstatus = ''
      this.trackInLaoding = false
      this.isTrackOut = true
      this.infoForm = {}
      this.$refs.tree.setCheckedKeys([])
      this.infoForm.lotId = lotId
      this.getlotInfo()
    },
    handleCancel() {
      const newObj = deepCopy({ ...this.infoForm, eqpId: this.eqpId })
      this.$refs.modelCancel.handleOpen(newObj)
    },
    handleTrackOut() {
      const newObj = deepCopy({ ...this.infoForm, eqpId: this.eqpId })
      this.$refs.modelTrackOut.handleOpen(newObj)
    },
    handleJobAbort() {
      this.$refs.modelJobAbort.handleOpen()
    },
    handleNodeClick(data, node) {
      if (data.disabled) return
      if (node.level === 4) {
        this.socket && this.socket.close()
        this.msgList = []
        this.eqpName = data.name
        this.eqpId = data.name
        this.$refs.tree.setCheckedKeys([data.id])
        // if (this.infoForm.trackInStatus) return
        getEqpStatusByEAP({ eqpId: data.name, lotId: this.infoForm.lotId }).then(res => {
          if (res.code === 1) {
            this.eqpstatus = res.data
          }
        })
        getToolingMaterialInfo({ eqpId: data.id }).then(res => {
          if (res.code === 1) {
            this.toolingTypeList = res.data.toolingTypeList.map(v => ({ typeName: v, barcode: '' }))
            this.materialTypeList = res.data.materialTypeList.map(v => ({ typeName: v, barcode: '' }))
            this.toolingList = res.data.toolingList
            this.isShow = res.data.isShow
          }
        })
        this.initSocket(data.id)
      }
    },
    queryInfo(data, node) {
      if (data.disabled) return
      getLotInfoByEqpId({ eqpId: data.name }).then(res => {
        if (res.code === 1) {
          // 就这样了, 要这这儿要哪儿的
          // if (res.data[0] && res.data[0].trackInStatus === 1) {
          //   }
          this.infoForm = res.data[0] || {}
          this.eqpstatus = res.data[0].eqpStatus || ''
          if (res.data[0].lotId) {
            this.isTrackOut = false
          } else {
            this.isTrackOut = true
          }
        } else {
          this.infoForm = {}
          this.eqpstatus = ''
          this.isTrackOut = true
        }
      }, () => {
        this.infoForm = {}
        this.eqpstatus = ''
        this.isTrackOut = true
      })
    },
    filterNode(value, data) {
      if (!value) return true
      return (data.name).toLowerCase().indexOf(value.toLowerCase()) !== -1
    },
    formatTree(root, disabledList = []) {
      return (root || []).map(node => {
        const { id, name, children } = node
        return {
          id,
          name,
          status: '',
          disabled: false,
          childList: this.formatTree(children, disabledList)
        }
      })
    },
    async getEqpTree() {
      const res = await getTreeList({ check: 1, addEqp: 1 })
      // 这里format的作用是绑定status 数据劫持
      this.treeData = this.formatTree(res.data)
    },
    getlotInfo() {
      this.beforeGetLotInfoInit().then(() => {
        getLotInfo(this.$clearNull({
          lotId: this.infoForm.lotId
        })).then(res => {
          if (res.code === 1) {
            this.infoForm = res.data || {}
            if (res.data.trackInStatus) {
            // 开
              this.isTrackOut = false
              this.eqpName = res.data.mesEqpId
              this.eqpId = res.data.mesEqpId
              // 默认选择tree
              this.$refs.tree.setCheckedKeys([res.data.mesEqpId])
              const format = (root, name) => {
                if (!root || !root.length) return
                for (const item of root) {
                  if (name === item.name) {
                    item.disabled = false
                  } else {
                    item.disabled = true
                  }
                  format(item.childList, name)
                }
              }
              // 自动展开
              this.defaultExpandedKeys = this.parentId(this.treeData, res.data.mesEqpId)
              format(this.treeData, res.data.mesEqpId)
            } else {
              // 修改状态方法
              const tree = (root, node) => {
                if (!root || !root.length) return

                for (const item of root) {
                  if (node.eqpId === item.name) {
                    item.status = node.status
                    // item.checkedTrackIn = true
                    this.arr.push(node)
                    return item
                  }
                  const find = tree(item.childList, node)
                  if (find) return find
                }
              }
              // 同下
              const expandedKeys = []
              res.data.availableEqps.forEach(c => {
              // 又要做为开批的自动展开
              // 没必要给defaultExpandedKeys.push
                expandedKeys.push(this.parentId(this.treeData, c.eqpId))
                tree(this.treeData, c)
              })
              // 简单的扁平化一下
              const arr = expandedKeys.filter(v => v).reduce((total, current) => {
                return total.concat(current)
              }, [])
              this.defaultExpandedKeys = arr
              // 这里单独循环两遍因为要设置disable属性
              const tree2 = (root) => {
                if (!root || !root.length) return
                for (const item of root) {
                // 只有IDLE状态才可以选中
                  if (!this.arr.map(c => c.eqpId).includes(item.name) || item.status !== 'IDLE') {
                    item.disabled = true
                  }
                  tree2(item.childList)
                }
              }
              tree2(this.treeData)

              // 又得加需求: 找不到的话则加个弹窗或者只要找到一个对应的就不需要弹窗
              if (res.data.availableEqps && res.data.availableEqps.length) {
                const ids = this.notExistenceList(this.treeData, res.data.availableEqps)
                // 只要找到一个就不用弹窗
                if (ids.length && ids.length >= res.data.availableEqps.length) {
                  this.$alert(`MES回复的设备[${ids}]不在EAP设备清单中`, this.$t('messageNotification'), {
                    confirmButtonText: this.$t('determine')
                  })
                }
              } else {
                this.$alert('无可用设备', this.$t('messageNotification'), {
                  confirmButtonText: this.$t('determine')
                })
              }
            }
          } else {
            this.$alert(replaceStr(this.$t(String(res.message)), res.data), this.$t('messageNotification'), {
              confirmButtonText: this.$t('determine')
            })
            this.infoForm = {}
          }
        })
      })
    },
    // 类似于初始化
    beforeGetLotInfoInit() {
      // 注意childList和children字段不同
      const formatTree = (root) => {
        return (root || []).map(node => {
          const { id, name, childList } = node
          return {
            id,
            name,
            status: '',
            disabled: false,
            childList: formatTree(childList)
          }
        })
      }
      return new Promise((resolve, reject) => {
        this.isTrackOut = true
        this.defaultExpandedKeys = []
        this.treeData = formatTree(this.treeData)
        this.eqpId = ''
        this.eqpName = ''
        resolve()
      })
    },
    handleTrackIn() {
      if (!this.validEqpValue()) return
      if (!this.infoForm.workOrder) return
      this.trackInLaoding = true
      checkToolingMaterialInfo({
        eqpId: this.eqpId,
        lotId: this.infoForm.lotId,
        productName: this.infoForm.product,
        toolingInfo: this.toolingTypeList,
        materialInfo: this.materialTypeList
      }).then(res => {
        if (res.code === 1) {
          doTrackIn(this.$clearNull({ eqpId: this.eqpId, lotId: this.infoForm.lotId, toolingList: this.toolingList })).then(res => {
            if (res.code === 1) {
              this.trackInLaoding = false
              this.isTrackOut = false
              this.$alert(replaceStr(this.$t(String(res.message)), res.data), this.$t('trackInInfo'), {
                confirmButtonText: this.$t('determine'),
                type: 'success'
              })
            } else {
              this.$alert(replaceStr(this.$t(String(res.message)), res.data), this.$t('trackInInfo'), {
                confirmButtonText: this.$t('determine'),
                type: 'error',
                callback: action => {
                  this.trackInLaoding = false
                  this.isTrackOut = true
                }
              })
            }
          }, rej => {
            this.trackInLaoding = false
            this.isTrackOut = true
          })
        } else {
          this.$alert(replaceStr(this.$t(String(res.message)), res.data), this.$t('trackInInfo'), {
            confirmButtonText: this.$t('determine'),
            type: 'error',
            callback: action => {
              this.trackInLaoding = false
              this.isTrackOut = true
            }
          })
        }
      }).catch(() => {
        this.trackInLaoding = false
        this.isTrackOut = true
      })
    },
    initSocket(eqpId) {
      const wsUrl = process.env.NODE_ENV === 'development' ? `ws://10.100.10.56:8070/ws/WebSocket/Connection?eqpid=${eqpId}`
        : `ws://${window.location.host}/ws/WebSocket/Connection?eqpid=${eqpId}`
      this.socket = new Socket({
        // url: `ws://10.100.10.56:8070/ws/WebSocket/Connection?eqpid=1`,
        url: wsUrl,
        // url: 'ws://localhost:8000',
        onmessage: this.onmessage
      })
    },
    onmessage(event) {
      console.log(event.data, 'websocket 接收到的信息')
      if (!event.data) return
      const data = JSON.parse(event.data)
      const { functionName, body } = data
      if (functionName === 'EAPToOUI_ShowUIMessage') {
        const year = new Date().getFullYear()
        const mouth = (new Date().getMonth() + 1) < 10 ? '0' + (new Date().getMonth() + 1) : (new Date().getMonth() + 1)
        const day = new Date().getDate()
        const hour = new Date().getHours() < 10 ? '0' + new Date().getHours() : new Date().getHours()
        const minutes = new Date().getMinutes() < 10 ? '0' + new Date().getMinutes() : new Date().getMinutes()
        const seconds = new Date().getSeconds() < 10 ? '0' + new Date().getSeconds() : new Date().getSeconds()

        const msgItem = { type: body.type, message: body.message, color: typeColor[body.type],
        // 下次再改
          date: `${year}-${mouth}-${day} ${hour}: ${minutes}: ${seconds}` }
        this.msgList.unshift(msgItem)
      } else if (functionName === 'EAPToOUI_EqpStatusChange') {
        // 3 Offline,4 Online-Local,5 Online-Remote
        const type = {
          3: 'Offline',
          4: 'Online-Local',
          5: 'Online-Remote'
        }
        this.eqpstatus = type[body.status]
        const { lotId } = this.infoForm.lotId
        updateEqpStatus({ eqpId: this.eqpId, lotId, eqpStatus: type[body.status] })
      }
      // action 操作
      if (body.action && body.action === 'TrackInFail') {
        this.isTrackOut = true
      } else {
        this.isTrackOut = false
      }
    },
    parentId(root, name, parentIdsList = []) {
      if (!root || !root.length) return
      for (const item of root) {
        if (item.name === name) {
          return parentIdsList
        }
        const find = this.parentId(item.childList, name, [...parentIdsList, item.id])
        if (find) return find
      }
    },
    validEqpValue() {
      if (!this.infoForm.lotId) {
        this.$notify({
          message: `${this.$t('pleaseInput')}${this.$t('LotNumebr')}`,
          type: 'warning'
        })
        return false
      } else if (!this.eqpId) {
        this.$notify({
          message: `${this.$t('pleaseInput')}${this.$t('eqpName')}`,
          type: 'warning'
        })
        return false
      }
      return true
    },
    notExistenceList(tree, idList) {
      const flatten = (root) => {
        return (root || []).reduce((total, current) => {
          return total.concat(current.name, flatten(current.childList))
        }, [])
      }
      const treeLists = flatten(tree)
      const ids = idList.map(c => c.eqpId)
      const notExistence = ids.filter(c => !(treeLists.includes(c)))
      return notExistence
    }
  }
}
</script>

<style scoped lang="scss">
.webOUI {
  padding: 10px 10px 43px 10px;
}
::v-deep .el-form .el-form-item {
  width: 48%;
  .el-form-item__content {
    width: calc(100% - 120px);
  }
}
.swiper-message {
  width: 100%;
  height: 200px;
  overflow-x: hidden;
  overflow-y: auto;
  margin-top: 20px;
  background-color: #fff;
  border: 1px solid #e6ebf5;
  border-radius: 4px;
  box-sizing: border-box;
  padding: 4px 10px;
  .swiper-content {
    width: 100%;
    height: 100%;
    .swiper-message-item {
      display: flex;
      justify-content: flex-start;
      padding: 5px 0;
      .item-message{
        flex: 1;
        display: inline-block;
      }
    }
  }
}
</style>
